package by.dkusch.aircompany.services.impl;

import java.util.List;
import java.util.Set;

import javax.persistence.metamodel.SingularAttribute;

import org.apache.commons.lang3.Validate;
import org.springframework.stereotype.Service;

import by.dkusch.aircompany.dao.UserAccountDao;
import by.dkusch.aircompany.dao.UserProfileDao;
import by.dkusch.aircompany.model.tables.UserAccount;
import by.dkusch.aircompany.model.tables.UserAccount_;
import by.dkusch.aircompany.model.tables.UserGrant;
import by.dkusch.aircompany.model.tables.UserProfile;
import by.dkusch.aircompany.model.tables.enums.FormType;
import by.dkusch.aircompany.services.UserService;

@Service
public class UserServiceImpl extends AbstractServiceImpl<Long, UserProfile> implements UserService {

	/* dao - is injected UserProfileDao */

	private UserAccountDao accountDao;

	public UserAccountDao getAccountDao() {
		return accountDao;
	}

	public void setAccountDao(UserAccountDao accountDao) {
		this.accountDao = accountDao;
	}

	@Override
	public void createNewUser(UserProfile profile, UserAccount account) {
		Validate.isTrue(profile.getId() == null,
				"This method should be called for 'not saved yet' profile only. Use UPDATE instead");

		profile.setUserAccount(account);
		dao.insert(profile);
	}

	@Override
	public void updateProfile(UserProfile profile) {
		dao.update(profile);
	}

	@Override
	public void removeUser(Long id) {
		dao.delete(id);
		accountDao.delete(id);
	}

	@Override
	public void deleteAll() {
		dao.deleteAll();
		accountDao.deleteAll();
	}

	@Override
	public UserAccount getAccountByEmail(String userName) {
		final List<UserAccount> allByFieldRestriction = accountDao.getAllByFieldRestriction(
				UserAccount_.email, userName);
		return !allByFieldRestriction.isEmpty() ? allByFieldRestriction.get(0) : null;
	}

	@Override
	public UserAccount getAccountById(Long id) {
		return accountDao.getById(id);
	}


	@Override
	public UserProfile getByIdWithLazyDetails(Long id) {
		return ((UserProfileDao) dao).getByIdWithLazyDetails(id);
	}

	@Override
	public Set<UserGrant> getGrants(UserProfile user) {
		Set<UserGrant> grants = ((UserProfileDao) dao).getGrants(user.getId());
		if (grants.size() == 0) {
			for (FormType type : FormType.values()) {
				UserGrant grant = new UserGrant();
				grant.setCode(type.name());
				grant.setUserProfile(user);
				grant.setFormId(type);
				grant.setDeleteFl(false);
				grant.setViewFl(false);
				grant.setEditFl(false);
				grants.add(grant);
			}
		}
		return grants;
	}

	@Override
	public boolean checkUniqueAccountFields(final SingularAttribute<UserAccount, String> attribute, final String value, final Long id) {
		List<UserAccount> result = accountDao.getAllByFieldRestrictionAnyCase(attribute, value);

		return (result == null) || (result.size() == 0) || ((result.size() == 1) && (result.get(0).getId() == id));
	}
}
